/* ==================================================================   
 * Created [2009-4-27 下午11:32:55] by Jon.King 
 * ==================================================================  
 * TSS 
 * ================================================================== 
 * mailTo:jinpujun@hotmail.com
 * Copyright (c) Jon.King, 2009-2012 
 * ================================================================== 
*/

package com.jinhe.tss.core.cachepool;

import java.util.List;

import com.jinhe.tss.core.cachepool.container.IPoolContainer;
import com.jinhe.tss.core.cachepool.strategy.CacheStrategy;


/** 
 * <p> SimplePool.java 
 * </p><p> 缓存池接口，提供了基本的缓存功能，包括存、取、删除、清空、重新载入等
 * </p><p> 缓存策略停用启用的控制用动态代理实现，涉及的操作有，getObject，putObject，check-out,check-in 
 * </p><p> 注:如果缓存池采用ehcache来存储对象,则key, value值必须继承Serializable接口
 * 
 * @author Jon.King 2006-12-31
 */
public interface IPool {
    
    /**
     * 初始化池
     */
    void init();
    
    /**
     * 获取池名称
     */
    String getName();
    
    /**
     * 根据key值从缓存池中获取一个对象。<br>
     * 如果获取不到，会自动调用loader.loadCacheObject(new TimeWrapper(key, null))来加载。<br>
     * 所以如果实现了ICacheLoader的loadCacheObject方法，应用缓存的地方不需要再手动执行putObject。<br>
     * 
     * 同时还要维护池的请求数、点击率的信息。<br>
     * 
     * @param key
     * @return
     */
    Cacheable getObject(Object key);
    
    /**
     * 根据key值从缓存池中获取一个对象。<br>
     * 因为getObject(Object key)方法会增加缓存项的点击率，所以实现本方法以供缓存池内部维护调用。<br>
     * 
     * @param key
     * @return
     */
    Cacheable getOldObject(Object key);

    /**
     * 将对象放入到缓存池中
     * @param key
     * @param value
     * @return
     */
    Cacheable putObject(Object key, Object value);

    /**
     * 从缓存池中移除一个对象。
     * @param key
     * @return
     */
    Cacheable removeObject(Object key);

    /**
     * 列举缓存池的所有缓存项
     * @return
     */
    List<Cacheable> listItems();
    
    /**
     * 列举缓存池的所有缓存项Key值
     * @return
     */
    List<CacheableKey> listKeys();
            
    /**
     * 刷新缓存,清除池中所有缓存项
     */
    void flush();
    
    /**
     * 刷新缓存项目, 将对象重新载入缓存池中.</p><p>
     * 该方法由各个具体应用到缓存池的应用自己继承ICacheLoader接口实现
     * @param obj
     * @return
     * @throws PoolException
     */
    Cacheable reload(Cacheable obj) throws RuntimeException ;
    
    /**
     * 返回池中对象的个数(对IObjectPool而言包括空闲状态的和check-out的)
     */
    int getSize();
    
    /**
     * 返回空闲状态的对象
     */
    IPoolContainer getFree() ;

    /**
     * 返回使用状态的对象
     */
    IPoolContainer getUsing();
    
    /************************************************************************************
     **********************  定义池的释放以及缓存项销毁等操作 ********************************
     ************************************************************************************/        
    
    /**
     * 销毁缓存项。</p><p>
     * 本方法会在release缓存池的时候被调用。
     * @param o
     */
    void destroyObject(final Cacheable o);
    
    /**
     * 释放所有池中的连接，并且关闭池。
     * @param 
     *       是否强制释放（true:强制销毁这些连接然后返回, fasle 等所有连接都返回再释放）
     */
    void release(final boolean forced);
    
    /**
     * 异步释放所有池中的连接，并且关闭池。本方法立即返回，一个后台的线程将被创建出来来释放池中连接。
     * @param 
     *       是否强制释放（true:强制销毁这些连接然后返回, fasle 等所有连接都返回再释放）
     */
    void releaseAsync(final boolean forced);

    /**
     * 设置是异步还是同步销毁对象。
     * 如果设置为true，那么之后每次销毁对象（过期的对象，或者是最终释放整个池）的时候，允许方法立即返回。
     * 当销毁对象很耗费时间的情况下，这种方式将会非常有用。
     */
    void setAsyncDestroy(boolean b);

    /**
     * 返回是否是异步销毁对象
     */
    boolean isAsyncDestroy();
    
    boolean isReleased();

    /************************************************************************************
    ************************************  监听器操作 ************************************
    ************************************************************************************/
    
    /**
     * 往事件通知列表里加入一个监听器
     * @param x
     */
    void addObjectPoolListener(IPoolListener x);

    /**
     * 从事件通知列表里移除指定监听器
     * @param x
     */
    void removeObjectPoolListener(IPoolListener x);
    
    /**
     * 根据事件类型触发事件
     * @param eventType
     */
    public void firePoolEvent(int eventType);
    
    /************************************************************************************
     ************************************    池扩展     **********************************
     ************************************************************************************/
    
    /**
     * 池点击率。(requests == 0) ? 0 : (((float)hits / requests) * 100f)</p><p>
     * 请求时获取的连接可能是池中已存在的连接，亦或者是新建出来的连接。</p><p>
     * 池点击率为这两者的比较，越大则说明池的机制越好，因为池的目的就是要尽可能的利用已创建的连接而不用去创建新的。
     */
    float getHitRate();
    
    long getRequests();

    /**
     * 将元素从free池中取出，放入using池中，并返回该元素。</p><p>
     * 如果没有空置的元素可以获取，则一个新的元素将会创建出来，除非到了池的上限值。</p><p>
     * 如果一个空置的元素是错误的，它将被移出对象池，将会重新获取另外一个元素出来。</p><p>
     * 如果池中没有空置的元素且已经到达池的最大容量，本方法将在指定的时间内等待，</p><p>
     * 期间如果有对象被check-in则返回该对象。
     * @param timeout
     * @return 
     *       池中的元素，如果没有可用对象返回null
     * @exception PoolException
     *       创建对象时出错则抛异常
     */
    Cacheable checkOut(long timeout);
    
    /**
     * 将对象重新返回到空闲(free)队列中。</p><p>
     * 将元素从using池中去除，放入using池中。</p><p>
     * 如果对象不在using池中，则返回失败。</p><p>
     * @param o
     */
    void checkIn(Cacheable o);
    
    /**
     * 根据缓存池中缓存策略设定的访问规则来从free池中移除一个缓存项。</p><p>
     * 本操作在check-out或者"缓存池溢出"的时候被调用。</p><p>
     * 如果移除一个后缓存池还是溢出状态，则本方法将会被反复调用，直到缓存池的容量不溢出为止。</p><p>
     * @return 
     *       池中的元素，如果没有可用对象返回null
     */
    Cacheable remove();
    
    /**
     * 清除池中过期的对象。</p><p>
     * 本方法将被cleaner线程调用来清理过期的对象。</p><p>
     * 注意，当类似对门户树进行缓存的时候需要对匿名门户树始终进行缓存，应用需要特殊实现purge()方法来实现</p><p>
     * 缓存池的清理工作，从而替代默认的清除方式。
     * @return
     *        如果清除后池为空，则返回false，否则true
     */
    boolean purge();
    
    
    /************************************************************************************
     ************************************    设置池     **********************************
     ************************************************************************************/
    
    /**
     * 设置池的算法
     * @param arithmetic
     * @see com.jinpj.cachepool.extend.IArithmetic
     */
    void setArithmetic(IArithmetic arithmetic);
    
    IArithmetic getArithmetic();

    /**
     * 设置池中缓存项载入类
     * @param arithmetic
     * @see com.jinpj.cachepool.extend.IArithmetic
     */
    void setLoader(ICacheLoader loader);
    
    /**
     * 修改对象的缓存策略信息
     * @param strategy
     */
    void setCacheStrategy(CacheStrategy strategy);
    
    CacheStrategy getCacheStrategy();
}

